package com.theta.gateway.facade.api.component.fiter;

import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpCookie;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import com.theta.gateway.biz.dto.request.AuthenticationValidateRequest;
import com.theta.gateway.biz.dto.response.AuthenticationValidateResponse;
import com.theta.gateway.biz.service.SsoAuthenticationService;
import com.theta.gateway.infra.common.base.Result;
import com.theta.gateway.infra.common.config.NacosConstantConfig;
import com.theta.gateway.infra.common.context.GatewayRequestContext;
import com.theta.gateway.infra.common.exception.BusinessException;
import com.theta.gateway.infra.common.exception.enums.ErrorEnum;
import com.theta.gateway.infra.common.utils.Base64Util;
import com.theta.gateway.infra.common.utils.GatewayRequestUtil;
import com.theta.gateway.infra.common.utils.JsonUtil;

import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;


@Slf4j
@Component
public class SsoUserAuthenticationGatewayFilterFactory extends AbstractGatewayFilterFactory<SsoUserAuthenticationGatewayFilterFactory.AuthenticationConfig> {

	
	@Autowired
	private SsoAuthenticationService ssoAuthenticationService;
	@Autowired
	private NacosConstantConfig nacosConstantConfig;
	
	public SsoUserAuthenticationGatewayFilterFactory() {
		super(AuthenticationConfig.class);
	}
	
	@Override
	public GatewayFilter apply(AuthenticationConfig config) {
		log.info("SsoUserAuthenticationGatewayFilterFactory...start  {}",config==null?"config is null":config.getName());
		return (exchange,chain)->{	
			ServerHttpRequest request=exchange.getRequest();
			ServerHttpResponse response=exchange.getResponse();
			log.info("SsoUserAuthenticationGatewayFilterFactory before -->{},{}",config.getName(),request.getPath());
			GatewayRequestContext requestContext=exchange.getAttribute(GatewayRequestContext.CACHE_GATEWAY_CONTEXT);
			if(requestContext==null) {
				log.error("获取网关解析参数为空...");
				GatewayRequestUtil.responseJson(response, new Result<Void>(ErrorEnum.ROUTE_PARAM_PARSE_ERROR.getCode(), ErrorEnum.ROUTE_PARAM_PARSE_ERROR.getMessage()));
				return null;
			}
			List<String> headers= requestContext.getHeaders().get(this.nacosConstantConfig.getSsoTokenName());
			MultiValueMap<String, HttpCookie> cookieMap = request.getCookies();
			HttpCookie ssoCookie= cookieMap.getFirst(this.nacosConstantConfig.getSsoCookieName());
			log.info("SsoUserAuthenticationGatewayFilterFactory ssocookie==>{}",ssoCookie==null?"":ssoCookie.getValue());
			String authentication=CollectionUtils.isEmpty(headers)?ssoCookie!=null?ssoCookie.getValue():"":headers.get(0);
			
//			String authentication=CollectionUtils.isEmpty(headers)?null:headers.get(0);
			AuthenticationValidateRequest validateRequest=new AuthenticationValidateRequest(config.getName(),authentication, request.getPath().toString());
			AuthenticationValidateResponse<Object> validateResp= this.ssoAuthenticationService.validateAuthentication(validateRequest,Object.class);
//			validateResp.setTokenAvailable(true);
			log.info("SsoUserAuthenticationGatewayFilterFactory AuthenticationValidateResponse -->{}",JsonUtil.toJsonString(validateResp));
			//token校验通过
			if(validateResp!=null && validateResp.getTokenAvailable()) {
				if(validateResp.getLoginProfile()!=null) {
					String loginProfile = JsonUtil.toJsonString(validateResp.getLoginProfile());
			        request = exchange.getRequest().mutate()
			        		.header("userProfile",Base64Util.encode2Str(loginProfile))
			        		.build();
				}
				return chain.filter(exchange.mutate().request(request).build())
						.then(Mono.fromRunnable(()->{
					log.info("SsoUserAuthenticationGatewayFilterFactory after -->{}",config.getName());
				}));
			}else {
				throw new BusinessException(ErrorEnum.NOT_LOGIN.getCode(),ErrorEnum.NOT_LOGIN.getMessage(),validateResp.getLoginUrl());
			}
		};
	}
	
	
	public static class AuthenticationConfig {
		private String name;

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}
		
	}

}
